/*!
 * # 模块 JS:
 *  Organization - 组织管理
 * 
 * # 描述:
 *  向系统管理人员提供组织结构、部门以及岗位的管理功能，包括为组织、部门或岗位添加用户，以及设置组织、部门或岗位的权限。
 * 
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

/*
 * @param {Object} $    jQuery 命名空间。
 * @param {Object} $$   pittypat 命名空间。
 * @param {Object} _mod 模块 Apps (应用与功能) 的命名空间。
 * 
 * 使用 pittypat.namespace('...') 以确保 _mod 命名空间是存在的。
 * 
 * 更多说明请参见：
 * https://www.pittypat.work/com/waln/pittypat/coding/help/index.html#js。
 */
(function ($, $$, _mod) {
    'use strict';

    $$.ui.msg = '...';

    /*
     * 为登录用户注册一个处理函数。
     * 由于没有为匿名用户注册处理函数，那么当发现用户尚未登录时，则会默认跳转到首页（登录页）。
     * 
     * 如果需要为匿名用户添加处理逻辑，应该使用如下格式的代码：
     * $$({
     *     authorized: function (_) {
     *         ...
     *     },
     *     anonymous: function (_) {
     *         // 跳转到自定义的登录页面
     *         window.location = '../../../../login.html';
     *     }
     * });
     * 
     * 如果需要自定义登录页面，则可能还需要添加 init 等处理函数。详细帮助请参见：
     * https://www.pittypat.work/com/waln/pittypat/ref/help/pittypat.js.html#pittypat。
     *
     * 参数 _ 的定义如下：
     * {
     *    user:  {Object},  // (只读)当前用户的用户信息
     *    app:   {Object},  // (只读)当前应用的命名空间，如果无法定位，则为 null
     *    mod:   {Object},  // (只读)当前模块的命名空间，如果无法定位，则为 null
     *    init:  {Boolean}, // (只读)是否正在初始化页面
     *    first: {Boolean}, // (只读)是否首次执行 authorized
     *    data:  {any}      // (读写)前述的 data 数据，或 data 函数返回的结果
     * }
     */
    $$(function (_) {
        var
            // 模块 UI 命名空间
            _ui = _mod.ui = _mod.ui || {},
            // 模块 API 命名空间
            _api = _mod.api,
            // body > main
            $main = $('main'),
            // #orgs
            $orgs = $('#orgs'),
            // #searchedUsers
            $searchedUsers = $('#searched-users');

        if (_.init) {
            function cmpByPosition(x, y) {
                return x.position - y.position;
            }

            function sortByPosition(v) {
                $$.util.array.sort(v, cmpByPosition);
            }

            // 在当前已经加载行数的基础上增加指定的行数
            function setLoadedSummary() {
                if (arguments.length < 1) {
                    return;
                }

                // 总行数和已加载行数
                var $loadedRows = $('#loaded-rows'),
                    $totalRows = $('#total-rows'),
                    totalRows = 0,
                    loadedRows = Long.fromString($loadedRows.text() || '0').add(arguments[0]);

                if (arguments.length == 1) {
                    // 此时认为只有提供了一个增量
                    totalRows = Long.fromString($totalRows.text() || '0').add(arguments[0]);
                } else {
                    // 第二个参数
                    totalRows = Long.fromValue(arguments[1]);
                }

                $loadedRows.text(loadedRows);
                $totalRows.text(totalRows);

                // 如果已经加载的行数等于或超过了总行数，隐藏加载更多按钮
                $('#load-more').css('display', loadedRows.gte(totalRows) ? 'none' : 'flex');
            }

            _ui.org = {
                /*
                 * Org 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-org">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="material-icons org-icon">language</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div>' +
                        '                <span class="model-prop model-org-name"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <button data-target-menu="#model-org-menu" class="mdc-ripple-surface mdc-ripple-surface--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">' +
                        '                <i class="material-icons">more_vert</i>' +
                        '            </button>' +
                        '            <i class="material-icons">expand_more</i>' +
                        '        </div>' +
                        '    </header>' +
                        '    <section>' +
                        '        <div class="depts"></div>' +
                        '        <div class="posts"></div>' +
                        '        <div class="users"></div>' +
                        '    </section>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $orgs;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-org').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.org.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.org.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.org.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $orgs;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.org.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.org.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $orgs;
                    }

                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $list.children('#model-org-' + model.id);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-org-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-org-name').text(model.name);

                        // 为设置权限设置一个代码
                        model.roleType = 1;
                    }

                    return $model;
                },

                /*
                 * 将指定的 App 对象对应的 DOM 元素从列表中移除。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $list 要从中移除元素的 DOM 列表。
                 */
                remove: function (args, model, $list) {
                    $('#model-org-' + args).remove();
                }
            };

            _ui.dept = {
                /*
                 * Dept 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-dept">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="material-icons dept-icon">domain</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div>' +
                        '                <span class="model-prop model-dept-name"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <button data-target-menu="#model-dept-menu" class="mdc-ripple-surface mdc-ripple-surface--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">' +
                        '                <i class="material-icons">more_vert</i>' +
                        '            </button>' +
                        '            <i class="material-icons">expand_more</i>' +
                        '        </div>' +
                        '    </header>' +
                        '    <section>' +
                        '        <div class="depts"></div>' +
                        '        <div class="posts"></div>' +
                        '        <div class="users"></div>' +
                        '    </section>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-dept').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.dept.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.dept.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.dept.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$$.util.is.int(pos)) {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.dept.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.dept.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $('#model-dept-' + (model ? model.id : args.id));
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-dept-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-dept-name').text(model.name);

                        // 为设置权限设置一个代码
                        model.roleType = 2;
                    }

                    return $model;
                },

                /*
                 * 将指定的 App 对象对应的 DOM 元素从列表中移除。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $list 要从中移除元素的 DOM 列表。
                 */
                remove: function (args, model, $list) {
                    $('#model-dept-' + args).remove();
                }
            };

            _ui.post = {
                /*
                 * Post 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-post">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="material-icons post-icon">group</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div>' +
                        '                <span class="model-prop model-post-name"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <button data-target-menu="#model-post-menu" class="mdc-ripple-surface mdc-ripple-surface--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">' +
                        '                <i class="material-icons">more_vert</i>' +
                        '            </button>' +
                        '            <i class="material-icons">expand_more</i>' +
                        '        </div>' +
                        '    </header>' +
                        '    <section></section>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-post').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.post.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.post.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.post.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$$.util.is.int(pos)) {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.post.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.post.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $('#model-post-' + (model ? model.id : args.id));
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-post-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-post-name').text(model.name);

                        // 为设置权限设置一个代码
                        model.roleType = 3;
                    }

                    return $model;
                },

                /*
                 * 将指定的 App 对象对应的 DOM 元素从列表中移除。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $list 要从中移除元素的 DOM 列表。
                 */
                remove: function (args, model, $list) {
                    $('#model-post-' + args).remove();
                }
            };

            /*
             * User 结构如下：
             * {
             * }
             */
            _ui.user = {
                /*
                 * User 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-user">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="material-icons lock-indicator">lock_outline</i>' +
                        '            <img class="model-user-face" src="../app.png" alt="" />' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div class="w-15">' +
                        '                <span class="pt-model-prop model-user-name"></span>' +
                        '            </div>' +
                        '            <div class="hidden-phone">' +
                        '                <span class="pt-model-prop model-user-description theme-text-2"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <button data-target-menu="#model-user-menu" class="mdc-ripple-surface mdc-ripple-surface--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">' +
                        '                <i class="material-icons">more_vert</i>' +
                        '            </button>' +
                        '            <i></i>' +
                        '        </div>' +
                        '    </header>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $users;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-user').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.user.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.user.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.user.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (args.pageIndex === '1') {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.user.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.user.insert(args, model, pos + i, $list);
                            });
                        }

                        // 检查应用图标图片是否加载成功，如果不成功，则显示默认的图标
                        $list.find('img.model-user-face').one('error', function () {
                            var $img = $(this), $parent = $img.parent();
                            $img.remove();
                            $parent.append('<i class="material-icons default-user-face">account_circle</i>');
                        });
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $('#model-user-' + model.pk);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-user-' + model.pk)
                            .data('model', model)
                            .children('header'),
                            $face = $h.find('.model-user-face');

                        if ($face.length < 1) {
                            $h.find('.default-user-face').remove();
                            $face = $('<img class="model-user-face" src="' + $$.web.url(model.faceUrl) + '" alt="" />').appendTo($h.children('.pt-row-icon'));
                        } else {
                            $face.attr('src', $$.web.url(model.faceUrl));
                        }

                        $h.find('.model-user-name').text(model.name + '(' + model.loginName + ')');
                        $h.find('.model-user-description').text(model.description);
                        $h.find('.lock-indicator').css('display', model.lockTime ? 'block' : 'none');

                        // 为设置权限设置一个代码
                        model.roleType = 4;
                    }

                    return $model;
                },

                /*
                 * 将指定的 App 对象对应的 DOM 元素从列表中移除。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $list 要从中移除元素的 DOM 列表。
                 */
                remove: function (args, model, $list) {
                    $('#model-user-' + args).remove();
                }
            };

            /*
             * User 结构如下：
             * {
             * }
             */
            _ui.searchedUser = {
                /*
                 * User 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-searched-user">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="material-icons lock-indicator">lock_outline</i>' +
                        '            <i class="pt-row-toggle material-icons mdc-ripple-surface mdc-ripple-surface--primary mdc-theme--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">check_box_outline_blank</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div>' +
                        '                <span class="pt-model-prop model-searched-user-name"></span>' +
                        '            </div>' +
                        '            <div class="w-5 hidden-phone">' +
                        '                <span class="pt-model-prop model-searched-user-no"></span>' +
                        '            </div>' +
                        '            <div class="w-7 hidden-phone">' +
                        '                <span class="pt-model-prop model-searched-user-mobile"></span>' +
                        '            </div>' +
                        '            <div class="w-13 hidden-phone">' +
                        '                <span class="pt-model-prop model-searched-user-email"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '    </header>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = searchedUsers;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-searched-user').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.searchedUser.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.searchedUser.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.searchedUser.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $searchedUsers;
                    }

                    if (args.pageIndex === '1') {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.searchedUser.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.searchedUser.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $('#model-searched-user-' + model.userId);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-searched-user-' + model.userId)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-searched-user-name').text(model.name + '(' + model.loginName + ')');
                        $h.find('.model-searched-user-no').text(model.no);
                        $h.find('.model-searched-user-mobile').text(model.mobile);
                        $h.find('.model-searched-user-email').text(model.email);
                        $h.find('.lock-indicator').css('display', model.lockTime ? 'block' : 'none');
                    }

                    return $model;
                },

                /*
                 * 将指定的 App 对象对应的 DOM 元素从列表中移除。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $list 要从中移除元素的 DOM 列表。
                 */
                remove: function (args, model, $list) {
                    $('#model-model-searched-' + args).remove();
                }
            };

            _ui.app = {
                /*
                 * App 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-app">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <img class="model-app-icon" src="../app.png" />' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div class="w-12">' +
                        '                <span class="pt-model-prop model-app-name"></span>' +
                        '            </div>' +
                        '            <div class="hidden-phone">' +
                        '                <span class="pt-model-prop model-app-description theme-text-2"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <i class="material-icons">expand_more</i>' +
                        '        </div>' +
                        '    </header>' +
                        '    <section></section>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $users;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-app').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.app.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.app.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.app.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $('#apps');
                    }

                    if (!$$.util.is.int(pos)) {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.app.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.app.insert(args, model, pos + i, $list);
                            });
                        }

                        // 检查应用图标图片是否加载成功，如果不成功，则显示默认的图标
                        $list.find('img.model-app-icon').one('error', function () {
                            this.parentElement.innerHTML = '<i class="material-icons">crop_original</i>';
                        });

                        $('.model-app').on('children', function (evt) {
                            var targetModel = $('#apps-dialog').data('model');
                            $$.ui.msg = '...';
                            _api.modules
                                // 传递应用的 id
                                .one('args', function (e) {
                                    e.args = {
                                        // 引用的 id
                                        appId: evt.model.id,
                                        // 当前用户的 id
                                        roleId: targetModel.roleType == 4 ? targetModel.userId : targetModel.id,
                                        roleType: targetModel.roleType
                                    };
                                })
                                .one('success', function (e) {
                                    sortByPosition(e.result);
                                    _ui.module.insertAll(e.args, e.result, -1, $('#model-app-' + e.args.appId + '>section'));
                                })
                                .one('load', function () {
                                    evt.childrenLoaded = true;
                                    $$.ui.msg = '';
                                })();
                        });
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $users;
                    }

                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $list.children('#model-app-' + model.id);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-app-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-app-icon').attr('src', $$.web.url('~/com/' + model.developerCode.toLowerCase() + '/' + model.identifier.toLowerCase() + '/app.png'));
                        $h.find('.model-app-name').text(model.name);
                        $h.find('.model-app-description').text(model.description);
                    }

                    return $model;
                }
            };

            _ui.module = {
                /*
                 * Module 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-module">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="pt-row-toggle material-icons mdc-ripple-surface mdc-ripple-surface--primary mdc-theme--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">check_box_outline_blank</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div class="w-8">' +
                        '                <span class="pt-model-prop model-module-name"></span>' +
                        '            </div>' +
                        '            <div>' +
                        '                <span class="pt-model-prop model-module-description theme-text-2"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '    </header>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $users;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-module').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.module.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.module.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.module.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$$.util.is.int(pos)) {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.module.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.module.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $list.children('#model-module-' + model.id);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-module-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-module-name').text(model.name);
                        $h.find('.model-module-description').text(model.description);

                        if (isPublicModule(model.id)) {
                            // 公共模块不应该做选择
                            $model.rowSelected(true);
                            $h.find('.pt-row-toggle').addClass('disabled');
                        } else {
                            $model.rowSelected(!!model.grantTime);
                            $h.find('.pt-row-toggle').removeClass('disabled');
                        }
                    }

                    return $model;
                }
            };

            _api.orgs
                .on('success', function (e) {
                    _ui.org.insertAll(e.args, e.result);
                })
                .on('load', function (e) {
                    $$.ui.msg = '';
                });

            $orgs
                .on('children', '.model-org,.model-dept', function (evt) {
                    // 避免冒泡到父级节点触发父级的 children 事件
                    evt.stopPropagation();

                    var $me = $(this);

                    $$.ui.msg = '...';
                    _api.deptChildren
                        // 传递应用的 id
                        .one('args', function (e) {
                            e.args = evt.model.id;
                        })
                        .one('success', function (e) {
                            var $sec = $me.children('section');
                            _ui.dept.insertAll(e.args, e.result.depts, -1, $sec.children('.depts'));
                            _ui.post.insertAll(e.args, e.result.posts, -1, $sec.children('.posts'));
                            _ui.user.insertAll(e.args, e.result.users, -1, $sec.children('.users'));
                        })
                        .one('load', function () {
                            evt.childrenLoaded = true;
                            $$.ui.msg = '';
                        })();
                })
                .on('children', '.model-post', function (evt) {
                    // 避免冒泡到父级节点触发父级的 children 事件
                    evt.stopPropagation();

                    var $me = $(this);
                    $$.ui.msg = '...';
                    _api.postUsers
                        // 传递岗位的 id
                        .one('args', function (e) {
                            e.args = evt.model.id;
                        })
                        .one('success', function (e) {
                            console.log(e.result);
                            _ui.user.insertAll(e.args, e.result, -1, $me.children('section'));
                        })
                        .one('load', function () {
                            evt.childrenLoaded = true;
                            $$.ui.msg = '';
                        })();
                });

            // 添加新组织
            _api.addOrg
                .on('args', function (e) {
                    e.args = {
                        name: $('#add-org-name').val(),
                        description: $('#add-org-description').val()
                    };
                })
                .on('success', function (e) {
                    _ui.org.insert(e.args, e.result, 0);

                    $('#add-org-name').val('');
                    $('#add-org-description').val('');
                });

            $('#add-org-dialog')
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.addOrg
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 设置组织资料
            _api.editOrg
                .on('success', function (e) {
                    _ui.org.update(e.args, e.result);
                });

            $('#edit-org-dialog')
                .on('opening', function (e) {
                    $('#edit-org-name').val(e.model.name);
                    $('#edit-org-description').val(e.model.description);
                })
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.editOrg
                        .one('args', function (e) {
                            e.args = {
                                id: okEvt.model.id,
                                name: $('#edit-org-name').val(),
                                description: $('#edit-org-description').val()
                            };
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 删除组织
            _api.deleteOrg
                .on('success', function (e) {
                    _ui.org.remove(e.args);
                })
                .on('load', function (e) {
                    $$.ui.msg = '';
                });

            $('#model-org-menu')
                .on('selected', function (evt) {
                    if (evt.selectedIndex == 5) {
                        $$.ui.confirm('确认删除',
                            '您确实要删除组织 ' + evt.model.name + ' 么？所有部门、岗位和人员设置都将被删除，并且无法恢复！',
                            function () {
                                $$.ui.msg = '...';
                                _api.deleteOrg
                                    .one('args', function (e) {
                                        e.args = evt.model.id;
                                    })();
                            });
                    }
                });

            // 添加新部门
            $('#add-dept-dialog')
                .on('ok', function (okEvt) {
                    var parent = okEvt.model;
                    $$.ui.msg = '...';
                    _api.addDept
                        .one('args', function (e) {
                            e.args = {
                                parentId: parent.id,
                                name: $('#add-dept-name').val(),
                                description: $('#add-dept-description').val()
                            };
                        })
                        .one('success', function (e) {
                            var $parent = $('#model-' + (parent.level ? 'dept' : 'org') + '-' + parent.id);
                            if ($parent.data('__children_loaded__')) {
                                _ui.dept.insert(e.args, e.result, 0, $parent.find('>section>.depts'));
                            } else {
                                $parent.rowExpanded(true);
                            }

                            $('#add-dept-name').val('');
                            $('#add-dept-description').val('');
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 设置部门资料
            _api.editDept
                .on('success', function (e) {
                    _ui.dept.update(e.args, e.result);
                });

            $('#edit-dept-dialog')
                .on('opening', function (e) {
                    $('#edit-dept-name').val(e.model.name);
                    $('#edit-dept-description').val(e.model.description);
                })
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.editDept
                        .one('args', function (e) {
                            e.args = {
                                id: okEvt.model.id,
                                name: $('#edit-dept-name').val(),
                                description: $('#edit-dept-description').val()
                            };
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 删除部门
            _api.deleteDept
                .on('success', function (e) {
                    _ui.dept.remove(e.args);
                })
                .on('load', function (e) {
                    $$.ui.msg = '';
                });

            $('#model-dept-menu')
                .on('selected', function (evt) {
                    if (evt.selectedIndex == 5) {
                        $$.ui.confirm('确认删除',
                            '您确实要删除部门 ' + evt.model.name + ' 么？所有下级部门、岗位和人员设置都将被删除，并且无法恢复！',
                            function () {
                                $$.ui.msg = '...';
                                _api.deleteDept
                                    .one('args', function (e) {
                                        e.args = evt.model.id;
                                    })();
                            });
                    }
                });

            // 添加新岗位
            $('#add-post-dialog')
                .on('ok', function (okEvt) {
                    var dept = okEvt.model;
                    $$.ui.msg = '...';
                    _api.addPost
                        .one('args', function (e) {
                            e.args = {
                                deptId: dept.id,
                                name: $('#add-post-name').val(),
                                description: $('#add-post-description').val()
                            };
                        })
                        .one('success', function (e) {
                            var $dept = $('#model-' + (dept.level ? 'dept' : 'org') + '-' + dept.id);
                            if ($dept.data('__children_loaded__')) {
                                _ui.post.insert(e.args, e.result, 0, $dept.find('>section>.posts'));
                            } else {
                                $dept.rowExpanded(true);
                            }

                            $('#add-post-name').val('');
                            $('#add-post-description').val('');
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 设置岗位资料
            _api.editPost
                .on('success', function (e) {
                    _ui.post.update(e.args, e.result);
                });

            $('#edit-post-dialog')
                .on('opening', function (e) {
                    $('#edit-post-name').val(e.model.name);
                    $('#edit-post-description').val(e.model.description);
                })
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.editPost
                        .one('args', function (e) {
                            e.args = {
                                id: okEvt.model.id,
                                name: $('#edit-post-name').val(),
                                description: $('#edit-post-description').val()
                            };
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            // 删除岗位
            _api.deletePost
                .on('success', function (e) {
                    _ui.post.remove(e.args);
                })
                .on('load', function (e) {
                    $$.ui.msg = '';
                });

            $('#model-post-menu')
                .on('selected', function (evt) {
                    if (evt.selectedIndex == 3) {
                        $$.ui.confirm('确认删除',
                            '您确实要删除岗位 ' + evt.model.name + ' 么？所有人员设置都将被删除，并且无法恢复！',
                            function () {
                                $$.ui.msg = '...';
                                _api.deletePost
                                    .one('args', function (e) {
                                        e.args = evt.model.id;
                                    })();
                            });
                    }
                });

            $('#edit-user-dialog')
                .on('opening', function (e) {
                    $('#edit-user-dialog-title').text(e.model.name + '(' + e.model.loginName + ')');
                    $('#edit-user-description').val(e.model.description);
                })
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.editUser
                        .one('args', function (e) {
                            e.args = {
                                pk: okEvt.model.pk,
                                description: $('#edit-user-description').val()
                            };
                        })
                        .one('success', function (e) {
                            okEvt.model.description = e.args.description;
                            $('#model-user-' + e.args.pk + '>header .model-user-description').text(e.args.description);
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            $('#search-users-dialog')
                .on('opening', function (e) {
                    $('#search-users-dialog-title').text(e.model.name);
                    $('#search-users-dialog').data('model', e.model);
                    $('#searched-users').empty();
                    $('#loaded-rows').text('0');
                    $('#total-rows').text('0');
                    $('#search-users-dialog-body>.pt-row').rowSelected(false);
                    $('#add-users-button').prop('disabled', true);
                })
                .on('ok', function (okEvt) {
                    $$.ui.msg = '...';
                    _api.editUser
                        .one('args', function (e) {
                            e.args = {
                                pk: okEvt.model.pk,
                                description: $('#edit-user-description').val()
                            };
                        })
                        .one('success', function (e) {
                            okEvt.model.description = e.args.description;
                            $('#model-user-' + e.args.pk + '>header .model-user-description').text(e.args.description);
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                            okEvt.done = true;
                        })();
                });

            _api.searchPostUsers
                .on('args', function (e) {
                    e.args = {
                        pageIndex: $('#search-users-page-index').val(),
                        keyword: $('#search-users-keyword').val(),
                        postId: $('#search-users-dialog').data('model').id
                    };
                })
                .on('success', function (e) {
                    _ui.searchedUser.insertAll(e.args, e.result.users);

                    if (e.args.pageIndex == '1') {
                        $('#loaded-rows').text('0');
                    }

                    // 总行数和已加载行数
                    setLoadedSummary(e.result.users.length, e.result.totalRows);
                })
                .on('load', function () {
                    $$.ui.msg = '';
                });

            _api.searchDeptUsers
                .on('args', function (e) {
                    e.args = {
                        pageIndex: $('#search-users-page-index').val(),
                        keyword: $('#search-users-keyword').val(),
                        deptId: $('#search-users-dialog').data('model').id
                    };
                })
                .on('success', function (e) {
                    _ui.searchedUser.insertAll(e.args, e.result.users);

                    if (e.args.pageIndex == '1') {
                        $('#loaded-rows').text('0');
                    }

                    // 总行数和已加载行数
                    setLoadedSummary(e.result.users.length, e.result.totalRows);
                })
                .on('load', function () {
                    $$.ui.msg = '';
                });

            // 搜索用户
            $('#search-users-button').on('click', function () {
                var model = $('#search-users-dialog').data('model');

                $('#search-users-page-index').val(1);
                $$.ui.msg = '...';
                if (model.roleType == 3) {
                    _api.searchPostUsers();
                } else {
                    _api.searchDeptUsers();
                }
            });

            // 加载更多
            $('#load-more').on('click', function () {
                var $pi = $('#search-users-page-index'),
                    pageIndex = Long.fromValue($pi.val()).add(1);

                $pi.val(pageIndex);

                var model = $('#search-users-dialog').data('model');

                $$.ui.msg = '...';
                if (model.roleType == 3) {
                    _api.searchPostUsers();
                } else {
                    _api.searchDeptUsers();
                }
            });

            // 全选按钮
            $('#search-users-dialog-body>.pt-row').on('beforeselect', function (e) {
                e.affectChildren = true;
            });

            // 确定删除按钮的显示状态
            $('#searched-users')
                .on('beforeselect', '.model-searched-user', function (e) {
                    e.affectParent = true;
                })
                .on('afterselect', '.model-searched-user', function (e) {
                    var has = e.selected || $('.model-searched-user.pt-row-selected').length > 0;
                    $('#add-users-button').prop('disabled', !has);
                });

            // 添加用户
            $('#add-users-button').on('click', function () {
                var ids = [];
                $('.model-searched-user.pt-row-selected').each(function () {
                    ids.push($(this).data('model').userId);
                });

                if (ids.length == 0) {
                    $$.ui.msg = '没有选中任何用户。';
                    return;
                }

                if (ids.length > 40) {
                    $$.ui.msg = '一次添加的用户不能超过 40 个。';
                    return;
                }

                var model = $('#search-users-dialog').data('model');
                $$.ui.msg = '...';
                if (model.roleType == 3) {
                    _api.addPostUsers
                        .one('args', function (e) {
                            e.args = {
                                postId: model.id,
                                ids: ids.join(',')
                            };
                        })
                        .one('success', function (e) {
                            ids.each(function (id) {
                                $('#model-searched-user-' + id).remove();
                            });

                            $('#search-users-dialog-body>.pt-row').rowSelected(false);
                            $('#add-users-button').prop('disabled', true);
                            setLoadedSummary(-ids.length);

                            var $post = $('#model-post-' + model.id);
                            if ($post.data('__children_loaded__')) {
                                _ui.user.insertAll(e.args, e.result, -1, $post.children('section'));
                            } else {
                                $post.rowExpanded(true);
                            }
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                        })();
                } else {
                    _api.addDeptUsers
                        .one('args', function (e) {
                            e.args = {
                                deptId: model.id,
                                ids: ids.join(',')
                            };
                        })
                        .one('success', function (e) {
                            ids.each(function (id) {
                                $('#model-searched-user-' + id).remove();
                            });

                            $('#search-users-dialog-body>.pt-row').rowSelected(false);
                            $('#add-users-button').prop('disabled', true);
                            setLoadedSummary(-ids.length);

                            var $dept = $('#model-' + (model.level ? 'dept' : 'org') + '-' + model.id);
                            if ($dept.data('__children_loaded__')) {
                                _ui.user.insertAll(e.args, e.result, -1, $dept.find('>section>.users'));
                            } else {
                                $dept.rowExpanded(true);
                            }
                        })
                        .one('load', function (e) {
                            $$.ui.msg = '';
                        })();
                }
            });

            $('#model-user-menu')
                .on('selected', function (evt) {
                    if (evt.selectedIndex == 2) {
                        $$.ui.msg = '...';
                        _api.removeUser
                            .one('args', function (e) {
                                e.args = evt.model.pk;
                            })
                            .one('success', function (e) {
                                _ui.user.remove(e.args);
                            })
                            .one('load', function () {
                                $$.ui.msg = '';
                            })();
                    }
                });

            _api.apps
                .on('before', function (e) {
                    e.cancel = !!$('#apps').data('loaded');
                })
                .on('success', function (e) {
                    sortByPosition(e.result);
                    _ui.app.insertAll(e.args, e.result);
                    $('#apps').data('loaded', true);
                })
                .on('load', function () {
                    // 折叠所有行，清空每一个应用下面的模块列表
                    $('.model-app').each(function () {
                        $(this).rowExpanded(false, true);
                    });
                    $$.ui.msg = '';
                });

            // 一个辅助函数，用于判断指定 id 的模块是否是公共模块
            function isPublicModule(id) {
                return (id == 'EeYoycXZXJ6INqReYNzHAA' || // 身份验证
                    id == 'EeY1g-7GCvCpNqReYNzHAA'); // 用户资料
            }

            // 设置权限
            $('#apps-dialog')
                .on('opening', function (openingEvt) {
                    $('#apps-dialog-title').text(openingEvt.model.name +
                        (openingEvt.model.roleType == 4 ? ('(' + openingEvt.model.loginName + ')') : ''));

                    $('#apps-dialog').data('model', openingEvt.model);
                    $$.ui.msg = '...';
                    // 加载 app 列表
                    _api.apps.one('args', function (e) {
                        e.args = openingEvt.model;
                    })();
                });

            $('#apps').on('afterselect', '.model-module', function (e) {
                if (isPublicModule(e.model.id)) {
                    return;
                }

                var targetModel = $('#apps-dialog').data('model');
                $$.ui.msg = '...';

                if (e.selected) {
                    // 授权
                    _api.grant
                        .one('args', function (argsEvt) {
                            argsEvt.args = {
                                moduleId: e.model.id,
                                roleId: targetModel.roleType == 4 ? targetModel.userId : targetModel.id,
                                roleType: targetModel.roleType
                            };
                        })
                        .one('load', function (loadEvt) {
                            $$.ui.msg = '';
                        })();
                } else {
                    // 取消授权
                    _api.revoke
                        .one('args', function (argsEvt) {
                            argsEvt.args = {
                                moduleId: e.model.id,
                                roleId: targetModel.roleType == 4 ? targetModel.userId : targetModel.id,
                                roleType: targetModel.roleType
                            };
                        })
                        .one('load', function (loadEvt) {
                            $$.ui.msg = '';
                        })();
                }
            });

            $main.mdcInit();
        }

        _api.orgs();
    });
})(jQuery, pittypat, pittypat.namespace('waln.authority.organization'));
